package com.google.code.virtualhockey.vhx.server.servlet.rpc

import com.google.gwt.user.server.rpc.RemoteServiceServlet
import java.util.logging.Logger
import com.google.code.virtualhockey.vhx.shared.rpc.{IResponse, ICommand, IRpcCommandService}

/**
 * Handles incoming RPC requests. A concrete subclass of this servlet needs to be created and
 * referenced in the application's WEB.XML file.
 */
abstract class RpcCommandServiceImpl extends RemoteServiceServlet with IRpcCommandService {
  protected val _log = Logger.getLogger( classOf[RpcCommandServiceImpl].getName )
  protected val _cmdContextProvider: TCommandContextProvider
  protected val _cmdHandlerLookup: TCommandHandlerLookup
  protected val _optSecurityTokenChecker: Option[TSecurityTokenChecker]

  /**
   * @see IRpcCommandService
   */
  def handle( strSecurityToken: String, command: ICommand[_] ): IResponse = {
    val ctx = createContext()
    checkSecurityToken(strSecurityToken)

    val handler: TCommandHandler[ICommand[IResponse],IResponse] = _cmdHandlerLookup.getHandler( command.asInstanceOf[ICommand[IResponse]] )
    handler.handle( ctx, command.asInstanceOf[ICommand[IResponse]] )
  }

  /**
   * Verifies the security token that has been provided during the last request.
   *
   * @param strSecurityToken the security token to be verified
   * @throws GDTWebSecurityException
   */
  protected def checkSecurityToken( strSecurityToken: String ) {
    if ( _optSecurityTokenChecker == None ) {
      if ( strSecurityToken != null )
        _log.warning( "No " + classOf[TSecurityTokenChecker].getName +
                      " is set although received security token '" +
                      strSecurityToken + "' is not null!")
    }
    else
      _optSecurityTokenChecker.get.checkSecurityToken( strSecurityToken, getThreadLocalRequest )
  }

  /**
   * Creates a new CommandContext. By default a basic context not requiring any
   * kind of authentication is created. Please override if you need to create
   * specific contexts incl. user authentication.
   *
   * @return a new context
   * @throws GDTWebServerException if there is a problem creating a new context
   */
  protected def createContext(): CommandContext = {
    return _cmdContextProvider.createContext( this, getThreadLocalRequest, getThreadLocalResponse )
  }
}
